#   Trolls Outta Luckland v0.0.7
#   Copyright 2009-2010, Gummbum
#
#   This file is part of Trolls Outta Luckland.
#
#   Trolls Outta Luckland is free software: you can redistribute it
#   and/or modify it under the terms of the GNU General Public License
#   as published by the Free Software Foundation, either version 3 of
#   the License, or (at your option) any later version.
#
#   Trolls Outta Luckland is distributed in the hope that it will be
#   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
#   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with Trolls Outta Luckland.  If not, see
#   <http://www.gnu.org/licenses/>.

__version__ = '0.0.7'

### Python imports
from os.path import join as join_path
from random import randrange

try:
    ### Pygame imports
    import pygame
    from pygame.locals import RLEACCEL
    ### Game library imports
    import enemy
    import game_globals
    from game_globals import *
    import gumm_sound
    from pixelperfect import get_colorkey_hitmask
    import player
    from sprite_strip_anim import SpriteStripAnim
    from ui import layout as ui_layout
    from utils import calc_line, rot_center
except ImportError, e:
    print 'ImportError: %s' % e
    print '    in file "%s"' % os.path.abspath(sys.argv[0])

(DEBRIS_RADIOACTIVE,
 DEBRIS_DERELICT,
 DEBRIS_CLAIMED,
 DEBRIS_EN_ROUTE,
 DEBRIS_SCAVAGED) = range(5)

game = None
jukebox = None

class DebrisExplodes(pygame.sprite.Sprite):
    def __init__(self, pos):
        pygame.sprite.Sprite.__init__(self)
        jukebox['enemy explodes'].play()
        self.pos = pos
        self.images = SpriteStripAnim(join_path('image', 'Explode1x200.png'),
            (0,1,48,48), 8, -1, False, game.fps.fps/12, name='debris_explodes')
        self.images.iter()
    def update(self, *args):
        try:
            self.image = self.images.next()
        except StopIteration:
            self.kill()
        self.rect = self.image.get_rect()
        self.rect.center = self.pos

class DebrisNova(pygame.sprite.Sprite):
    def __init__(self, pos, delay=0):
        pygame.sprite.Sprite.__init__(self)
        self.pos = pos
        self.images = SpriteStripAnim(join_path('image', 'Explode4x200.png'),
            (0,1,48,48), 8, -1, False, game.fps.fps/12, name='debris_nova')
        self.image = pygame.surface.Surface((1,1)).convert()
        self.image.fill((1,1,1))
        self.image.set_colorkey((1,1,1), RLEACCEL)
        self.rect = self.image.get_rect()
        self.rect.center = pos
        self.images.iter()
        self.delay = delay
        self.update()
    def update(self, *args):
        if self.delay > 0:
            self.delay -= game.speed()
        else:
            try:
                self.image = self.images.next()
            except StopIteration:
                self.kill()
            self.rect = self.image.get_rect()
            self.rect.center = self.pos

class ExtraShipDebris(pygame.sprite.Sprite):
    """Extra Ship powerup"""
    def __init__(self, image, pos):
        pygame.sprite.Sprite.__init__(self)
        #
        sz = 24
        self.colorkey = Color(1,1,1)
        circle = pygame.surface.Surface((sz,sz)).convert()
        circle.fill(self.colorkey)
        debris = circle.copy()
        rect = circle.get_rect()
        pygame.draw.circle(circle, Color('white'), rect.center, sz/2)
        circle.set_colorkey(Color('white'), RLEACCEL)
        rect.center = image.get_rect().center
        debris.blit(image, (0,0), rect)
        debris.blit(circle, (0,0))
        debris.set_colorkey(self.colorkey, RLEACCEL)
        #
        self.stock_image = debris
        self.image = self.stock_image
        self.stock_rect = self.image.get_rect()
        self.rect = self.stock_rect.copy()
        self.rect.center = pos
        self.hitmask = get_colorkey_hitmask(
            self.image, self.rect, key=self.colorkey)
        self.angle = 0
        self.mode = DEBRIS_RADIOACTIVE
        game.groups.add(self, layer='powerups')
        ## radioactive for 5 seconds - can't claim yet
        self.countdown = 5 * game.max_fps
        ## 200 grades of alpha to increment
        self.alpha = 55
        ## so for 5 seconds, each video frame must increment this much
        self.alpha_step = 200.0 / (5 * game.max_fps)
        self.speed = PLAYER_SPEED
    def update(self, *args):
        # DEBRIS_RADIOACTIVE -> DEBRIS_DERELICT -> DEBRIS_CLAIMED ->
        #  DEBRIS_EN_ROUTE -> DEBRIS_SCAVAGED
        if self.angle >= 360:
            self.angle = 0
        self.image = rot_center(self.stock_image, self.angle)
        self.angle += 1
        if self.mode == DEBRIS_RADIOACTIVE:
            if self.countdown > 2 * game.max_fps:
                self.countdown -= 1
                self.alpha += self.alpha_step
            elif self.countdown > 0:
                self.countdown -= 1
                if round(self.countdown) % 3 == 0:
                    self.alpha = 255
                else:
                    self.alpha = 100
            else:
                self.mode = DEBRIS_DERELICT
            self.image.set_alpha(self.alpha)
        elif self.mode == DEBRIS_CLAIMED:
            sound = jukebox.load_sound(
                join_path('sound','31882__HardPCM__Chip045.ogg'),
                'debris claimed', volume=0.4, sound_type=SOUND_FX)
            sound.play_mutex()
            self.mode = DEBRIS_EN_ROUTE
            self.slot = game.parts_shop.get_slot()
            self.path = calc_line(self.rect.center, self.slot)
            self.step = 0
        elif self.mode == DEBRIS_EN_ROUTE:
            if self.step >= len(self.path):
                self.mode = DEBRIS_SCAVAGED
                game.parts_shop.add(self)
            else:
                self.rect.center = self.path[self.step]
                self.step += 1
    def hit(self, other):
        if self.countdown > 0:
            pass
        elif other is game.player:
            if self.mode == DEBRIS_DERELICT:
                self.mode = DEBRIS_CLAIMED
                game.score.add(500, 2, self.rect.center)
        elif issubclass(type(other), player.LaserBlast):
            if self.mode == DEBRIS_DERELICT:
                self.explode()
                other.kill()
                game.score.add(500, 0, self.rect.center)
        elif issubclass(type(other), (enemy.Enemy,enemy.LaserBlast)):
            if self.mode == DEBRIS_DERELICT:
                self.explode()
                other.kill()
    def explode(self):
        self.kill()
        game.groups.add(
            DebrisExplodes(self.rect.center), layer='powerups', over=True)
    def nova(self):
        self.kill()
        game.groups.add(
            DebrisNova(self.rect.center), layer='powerups', over=True)

class PartsShop(object):
    def __init__(self):
        global game, jukebox
        game = game_globals.game
        jukebox = gumm_sound.jukebox
        self.rect = pygame.Rect(0,0,40,40)
        self.rect.topleft = game.ship_counter.max_size()
        self.rect.bottom = game.window.rect.bottom
        self.parts = []
        self.slot = 0
    def get_slot(self):
        """return center pos of the "slot" """
        if self.slot > 2:
            self.slot = 0
        x = self.rect.x
        w = self.rect.width
        cy = self.rect.centery
        slot = x+self.slot*w+w/2, cy
        self.slot += 1
        return slot
    def add(self, part):
        self.parts.append(part)
        if len(self.parts) == 3:
            self.new_ship()
    def lose(self):
        """powerups lost, explode them"""
        for s in game.groups.powerups.sprites():
            if issubclass(type(s), ExtraShipDebris):
                s.explode()
        self.slot = 0
        del self.parts[:]
    def new_ship(self):
        """powerups in the shop go nova, making a new ship"""
        jukebox.load_sound(
            join_path('sound','58919__mattwasser__coin_up.ogg'),
            'debris nova', sound_type=SOUND_FX).play()
        for s in game.groups.powerups.sprites():
            if issubclass(type(s), ExtraShipDebris) and \
            s.mode == DEBRIS_SCAVAGED:
                s.nova()
        game_globals.game.score.add(500, 5, game.ship_counter.rect.topright)
        game.ship_counter.gain()
        del self.parts[:]
    def reset(self):
        """quiet reset"""
        for s in game.groups.powerups.sprites():
            if issubclass(type(s), ExtraShipDebris):
                s.kill()
        self.slot = 0
        del self.parts[:]
